/**************************************************************************//**
 * @item     CosyOS-III Port
 * @file     port_cmx_s.c
 * @brief    CMSIS Cortex-M Core Port File
 * @author   迟凯峰
 * @version  V1.0.1
 * @date     2025.02.15
 ******************************************************************************/

#include "..\System\os_var.h"
#ifdef __PORT_CMX_H

/*
 * 用户定义
 */

// 1、是否启用内嵌汇编移植方案？（0：禁用；1：启用）
#define CMXPRT_ARM                      1

// 2、指令集架构（0：ARMv6-M；1：ARMv7-M）
#define CMXPRT_ISA                      1

////////////////////////////////////////////////////////////////////////////////

#if CMXPRT_ARM == 1

/* PendSV软中断 */
__ASM void OS_PendSV_Handler(void)
{
                IMPORT  sPendSV_Handler
                IMPORT  s_task_current
                IMPORT  s_task_news
                PRESERVE8

                push    {lr}

                bl      sPendSV_Handler
// 直接返回吗？
                IF CMXPRT_ISA == 0
                cmp     r0, #0
                beq     __RETURN
                ELSE
                cbz     r0, __RETURN
                ENDIF

                isb
// 保护现场吗？
                ldr     r1, =s_task_current
                subs    r0, #1
                IF CMXPRT_ISA == 0
                cmp     r0, #0
                beq     __RESTORE
                ELSE
                cbz     r0, __RESTORE
                ENDIF

                mrs     r0, psp

            IF SYSCFG_TASKPC_MONITOR == 1
// 任务PC监控
                IMPORT  s_sign_taskmgr
                IMPORT  s_pc
                ldr     r3, =s_sign_taskmgr
                ldrb    r3, [r3]
                IF CMXPRT_ISA == 0
                cmp     r3, #0
                beq     __PROTECTING
                ELSE
                cbz     r3, __PROTECTING
                ENDIF
                mov     r3, r0
                adds    r3, #24
                ldmia   r3, {r2}
                ldr     r3, =s_pc
                str     r2, [r3]

            ENDIF
// 保护现场
__PROTECTING
            IF MCUCFG_ASPEN_LSPEN == 1

                vstmdb  r0!, {s16-s31}

            ENDIF

            IF CMXPRT_ISA == 0

                subs    r0, #MCUCFG_CALLEE_PUSH_REG
                ldr     r2, [r1]
                str     r0, [r2]
                stmia   r0!, {r4-r7}
                mov     r4, r8
                mov     r5, r9
                mov     r6, r10
                mov     r7, r11
                stmia   r0!, {r4-r7}

            ELSE

                stmdb   r0!, {r4-r11}
                ldr     r2, [r1]
                str     r0, [r2]

            ENDIF
// 恢复现场
__RESTORE       ldr     r3, =s_task_news
                ldr     r3, [r3]
                str     r3, [r1]
                ldr     r0, [r3]

            IF CMXPRT_ISA == 0

                adds    r0, #16
                ldmia   r0!, {r4-r7}
                mov     r11, r7
                mov     r10, r6
                mov     r9, r5
                mov     r8, r4
                mov     r1, r0
                subs    r1, #MCUCFG_CALLEE_PUSH_REG
                ldmia   r1!, {r4-r7}

            ELSE

                ldmia   r0!, {r4-r11}

            ENDIF

            IF MCUCFG_ASPEN_LSPEN == 1

                vldmia  r0!, {s16-s31}

            ENDIF

                msr     psp, r0
// 返回
__RETURN        pop     {pc}

                ALIGN
}



/* 中断挂起服务装载器 */
#if MCUCFG_PENDSVFIFO_DEPTH > 0
__ASM void mPendSV_FIFOLoader(void *sv)
{
                IMPORT  mPendSV_FIFO_P0
                IMPORT  mPendSV_FIFO_P1
                IMPORT  m_sign_fifo

                ldr     r3, =m_sign_fifo
                ldrb    r3, [r3]
                IF CMXPRT_ISA == 0
                cmp     r3, #0
                beq     __FIFO1
                ELSE
                cbz     r3, __FIFO1
                ENDIF

__FIFO0         ldr     r1, =mPendSV_FIFO_P0
                b       __LOAD

__FIFO1         ldr     r1, =mPendSV_FIFO_P1

            IF MCUCFG_PENDSVFIFO_MUTEX == 1   // 互斥访问指令

__LOAD          ldrex   r2, [r1]
                adds    r2, #4
                strex   r3, r2, [r1]
                cmp     r3, #0
                bne     __LOAD

            ELIF MCUCFG_PENDSVFIFO_MUTEX == 2 // 互斥访问机制

                IMPORT  mPendSV_FIFO_P2
                IMPORT  m_sign_load

__LOAD          push    {r0, r4}
                mov     r0, r7     // 保护 r7

                ldr     r3, =m_sign_load
                ldrb    r4, [r3]   // 保护 m_sign_load
                movs    r2, #1
                strb    r2, [r3]   // 设置 m_sign_load
// 互斥访问 LOOP
__LOOP          mov     r7, r1
                ldr     r2, [r7]
                adds    r2, #4
                str     r2, [r7]
                cmp     r7, r1
                bne     __LOOP

                strb    r4, [r3]   // 恢复 m_sign_load
// 重设或恢复 r7
                IF CMXPRT_ISA == 0
                cmp     r4, #0
                beq     __RESR7
                ELSE
                cbz     r4, __RESR7
                ENDIF
                ldr     r7, =mPendSV_FIFO_P2 // 重设 r7
                b       __OVER
__RESR7         mov     r7, r0     // 恢复 r7
__OVER          pop     {r0, r4}

            ELIF MCUCFG_PENDSVFIFO_MUTEX == 3 // 关闭总中断

__LOAD          mrs     r3, primask
                cpsid   i
                ldr     r2, [r1]
                adds    r2, #4
                str     r2, [r1]
                msr     primask, r3

            ENDIF

                str     r0, [r2]
                bx      lr

                ALIGN
}
#endif

#endif

#endif
